package com.government.framework.web.service;

import cn.hutool.core.util.StrUtil;
import com.government.common.enums.SmTemplateCode;
import com.government.common.exception.ServiceException;
import com.government.common.utils.MessageUtils;
import com.government.sequence.key.SequenceKeyGenerator;
import com.government.system.service.IMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;


/**
 * @Copyright (C), 2018, 上海金皿计算机科技有限公司
 * @ProjectName: Phantom
 * @FileName: VerifyCodeServiceImpl.java
 * @Author: Kevin.Liu
 * @Date: 2019/5/13 14:13
 * @Description: 验证码相关服务
 * @email ==>> liuyufeng@midaigroup.com | kevin_24150@163.com
 * @History: <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号             描述
 */
@Slf4j
@Service
public class VerifyCodeService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private IMessageService messageService;


    public String sendCode(String phone, SmTemplateCode templateCode) throws ExecutionException, InterruptedException {
        String subKey = StrUtil.builder()
                .append(templateCode.getType())
                .append(StrUtil.COLON)
                .append(phone)
                .toString();
        SequenceKeyGenerator keyGenerator = SequenceKeyGenerator.VC_KEY().buildKey(subKey);

        // 手机号一天最大发送数量限制
        checkSmsLimit(phone);


        String vCode = MessageUtils.verifyCode();
        messageService.sendSms(phone, vCode);
        redisTemplate.opsForValue().set(keyGenerator.getKey(), vCode);
        return vCode;
    }

    /**
     * 做当天最大限制和设备最大限制校验
     *
     * @param phone
     */
    private void checkSmsLimit(String phone) {

        //当天限制缓存key
        SequenceKeyGenerator vcDayKey = SequenceKeyGenerator.VC_LIMIT_KEY().buildKey("day" + StrUtil.COLON + phone);

        /*一天內最大數*/
        Long dayNum = 0L;
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        operations.setIfAbsent(vcDayKey.getKey(), BigDecimal.ZERO.toString(), vcDayKey.expireSeconds(), TimeUnit.SECONDS);
        if (redisTemplate.hasKey(vcDayKey.getKey())) {
            dayNum = Long.parseLong(redisTemplate.opsForValue().get(vcDayKey.getKey()));
        }

        Long dayNumLimit = 10L;

        if (dayNum != null) {
            ServiceException.throwExOnCondition(dayNum >= dayNumLimit, "当日验证码发送数量已达到上限");

            operations.increment(vcDayKey.getKey(), 1);
        } else {
            redisTemplate.opsForValue().set(vcDayKey.getKey(), "1");
        }
    }

    public String verify(String phone, SmTemplateCode templateCode,String code) {
        //生产缓存的key
        String subKey = StrUtil.builder()
                .append(templateCode.getType())
                .append(StrUtil.COLON)
                .append(phone)
                .toString();
        SequenceKeyGenerator keyGenerator = SequenceKeyGenerator.VC_KEY().buildKey(subKey);

        String vCode = redisTemplate.opsForValue().get(keyGenerator.getKey());
        ServiceException.throwExOnCondition(StrUtil.isBlank(vCode), "验证码已经失效");
        ServiceException.throwExOnCondition(!StrUtil.equalsIgnoreCase(vCode, code), "验证码错误");

        return keyGenerator.getKey();
    }


}
